using Test
using Aqua
using NSEMSolver

@testset "Aqua Quality Assurance Tests" begin
    # Test the package with Aqua.jl
    # These tests ensure the package follows Julia best practices
    
    @testset "General Aqua Tests" begin
        Aqua.test_all(
            NSEMSolver;
            # Disable ambiguities test for now due to method extensions
            ambiguities = false,
            # Disable deps_compat test as it requires newer package versions
            deps_compat = false,
            # Disable piracies test for visualization extensions
            piracies = false
        )
    end
    
    @testset "Ambiguities" begin
        # Test for method ambiguities
        # Allow some ambiguities from extension packages
        Aqua.test_ambiguities(NSEMSolver; broken = false)
    end
    
    @testset "Dependencies Compatibility" begin
        # Test that all dependencies have proper version bounds
        Aqua.test_deps_compat(NSEMSolver)
    end
    
    @testset "Piracies" begin
        # Test for type piracy (defining methods on types from other packages)
        # This is important for ecosystem compatibility
        Aqua.test_piracies(NSEMSolver)
    end
    
    @testset "Project Structure" begin
        # Test that Project.toml is properly structured
        Aqua.test_project_toml_formatting(NSEMSolver)
    end
    
    @testset "Stale Dependencies" begin
        # Test for unused dependencies in Project.toml
        Aqua.test_stale_deps(NSEMSolver; ignore = [:Random, :Printf])
    end
    
    @testset "Persistent Tasks" begin
        # Test for persistent tasks (background tasks that might not terminate)
        Aqua.test_persistent_tasks(NSEMSolver)
    end
end

@testset "Custom Package Quality Tests" begin
    @testset "Export Consistency" begin
        # Ensure all exported symbols are documented
        exported_symbols = names(NSEMSolver)
        for symbol in exported_symbols
            if !startswith(string(symbol), "_") && symbol != :NSEMSolver
                @test hasmethod(Core.eval(NSEMSolver, symbol), ()) ||
                      isdefined(NSEMSolver, symbol)
            end
        end
    end
    
    @testset "Module Structure" begin
        # Test basic module structure
        @test isdefined(NSEMSolver, :solve_navier_stokes_2d)
        @test isdefined(NSEMSolver, :NSOptions)
        @test isdefined(NSEMSolver, :NSResult)
        
        # Test that core types are exported
        @test :NSOptions in names(NSEMSolver)
        @test :NSResult in names(NSEMSolver)
        @test :solve_navier_stokes_2d in names(NSEMSolver)
    end
    
    @testset "Performance Standards" begin
        # Basic allocation tests
        options = NSOptions(N=3, nu=0.1, tfinal=0.1, verbose=false)
        
        # Test that creating options doesn't allocate excessively
        allocs = @allocated NSOptions()
        @test allocs < 1000  # Should be minimal allocation
        
        # Test that basic function calls are type-stable
        @inferred NSOptions()
        @inferred NSOptions(N=4)
    end
    
    @testset "Documentation Coverage" begin
        # Test that main functions have docstrings
        main_functions = [:solve_navier_stokes_2d, :NSOptions, :NSResult]
        
        for func in main_functions
            if isdefined(NSEMSolver, func)
                docs = Base.Docs.doc(Core.eval(NSEMSolver, func))
                @test !isempty(string(docs))
            end
        end
    end
end